package app

import (
	"bytes"
	"context"
	"encoding/json"
	"gitee.com/zhucheer/orange/logger"
	"gitee.com/zhucheer/orange/request"
	"gitee.com/zhucheer/orange/session"
	"net/http"
	"sync"
)

type Context struct {
	response     http.ResponseWriter
	request      *http.Request
	ctx          context.Context
	session      session.Store
	responseBody bytes.Buffer
	OrangeInput  *request.OrangeInput
	CsrfToken    string
	userParams   map[string]interface{}
	mutx         sync.Mutex
}

func NewCtx(ctx context.Context, w http.ResponseWriter, r *http.Request) *Context {
	return &Context{
		ctx:      ctx,
		response: w,
		request:  r,
	}
}

func (c *Context) SetRW(w http.ResponseWriter, r *http.Request) {
	c.response = w
	c.request = r
}

func (c *Context) ResponseWrite(b []byte) error {
	_, err := c.responseBody.Write(b)
	return err
}

func (c *Context) ResponseHeader() http.Header {
	return c.response.Header()
}

func (c *Context) Header() http.Header {
	return c.request.Header
}

func (c *Context) Session() session.Store {
	if c.session == nil {
		logger.Warning("session is not open")
		return nil
	}
	return c.session
}

func (c *Context) SetCtxParam(key string, value interface{}) {
	c.mutx.Lock()
	defer c.mutx.Unlock()

	if c.userParams == nil {
		c.userParams = make(map[string]interface{})
	}
	c.userParams[key] = value
}

func (c *Context) GetCtxParam(key string) (val interface{}) {
	if c.userParams == nil {
		return
	}
	if val, ok := c.userParams[key]; ok {
		return val
	}
	return
}

func (c *Context) SetCookie(cookie *http.Cookie) {
	http.SetCookie(c.response, cookie)
}

func (c *Context) Request() *http.Request {
	return c.request
}

func (c *Context) Context() context.Context {
	return c.ctx
}

func (c *Context) ToJson(data interface{}) error {
	c.response.Header().Set("Content-Type", "application/json;charset=UTF-8")
	jsonBytes, err := json.Marshal(data)
	if err != nil {
		c.response.WriteHeader(500)
		c.response.Write([]byte(err.Error()))
		return err
	}
	c.ResponseWrite(jsonBytes)
	return nil
}

func (c *Context) ToString(data string) error {
	c.response.Header().Set("Content-Type", "text/html;charset=UTF-8")

	c.ResponseWrite([]byte(data))
	return nil
}
